package io.github.erehmi.library.vkb;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;

import io.github.erehmi.library.util.IMMUtils;

/**
 * Manipulate the soft & virtual keyboard showing or hiding.
 *
 * @author WhatsAndroid
 */
public class VirtualKeyboardController {
    private static final String TAG = "VKBC";

    private Context mContext;
    private LayoutManager mLayoutManager;

    public VirtualKeyboardController(Context context) {
        mContext = context;
    }

    public void setLayoutManager(LayoutManager layoutManager) {
        mLayoutManager = layoutManager;
        mLayoutManager.mVirtualKeyboardView.setVisibility(View.GONE);
        mLayoutManager.addOnGlobalLayoutListener();
    }

    public void showVirtualKeyboard() {
        mLayoutManager.showVirtualKeyboardView();
        if (mLayoutManager.mFocusView != null) {
            IMMUtils.hideSoftInput(mContext, mLayoutManager.mFocusView);
        }
    }

    public void hideVirtualKeyboard() {
        hideVirtualKeyboard(true);
    }

    public void hideVirtualKeyboard(boolean shouldShowSoftInput) {
        if (mLayoutManager.mFocusView != null && shouldShowSoftInput) {
            IMMUtils.showSoftInput(mContext, mLayoutManager.mFocusView);
        }

        mLayoutManager.hideVirtualKeyboardView(!shouldShowSoftInput);
    }

    public boolean isVirtualKeyboardShown() {
        return mLayoutManager.isVirtualKeyboardViewShown();
    }

    public void toggleVirtualKeyboard() {
        if (isVirtualKeyboardShown()) {
            hideVirtualKeyboard();
        } else {
            showVirtualKeyboard();
        }
    }

    /**
     * Manipulate the views' layout and the virtual keyboard showing status.
     */
    public static abstract class LayoutManager {
        private Context mContext;
        private View mAnchorView;
        private View mFocusView;
        private View mVirtualKeyboardView;

        private int mVirtualKeyboardViewHeight = 0;

        public LayoutManager(Context context) {
            mContext = context;
        }

        public Context getContext() {
            return mContext;
        }

        public View getAnchorView() {
            return mAnchorView;
        }

        public void setAnchorView(View anchorView) {
            mAnchorView = anchorView;
        }

        public void setSoftInputFocusView(View focusView) {
            mFocusView = focusView;
        }

        protected View getFocusView() {
            return mFocusView;
        }

        public void setVirtualKeyboardView(View view) {
            mVirtualKeyboardView = view;
        }

        protected View getVirtualKeyboardView() {
            return mVirtualKeyboardView;
        }

        public void addOnGlobalLayoutListener() {
            mVirtualKeyboardView.getViewTreeObserver()
                    .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                        @Override
                        public void onGlobalLayout() {
                            int virtualKeyboardSuggestedHeight = getVirtualKeyboardSuggestedHeight();
                            if (mVirtualKeyboardView != null && !isVirtualKeyboardViewShown()) {
                                onVirtualKeyboardViewHide();
                                if (mVirtualKeyboardViewHeight != virtualKeyboardSuggestedHeight) {
                                    mAnchorView.requestLayout();
                                }
                            }
                            mVirtualKeyboardViewHeight = virtualKeyboardSuggestedHeight;
                        }
                    });
        }

        void showVirtualKeyboardView() {
            LayoutParams layoutParams = mVirtualKeyboardView.getLayoutParams();
            layoutParams.height = mVirtualKeyboardViewHeight = getVirtualKeyboardSuggestedHeight();
            mVirtualKeyboardView.setLayoutParams(layoutParams);
            mVirtualKeyboardView.setVisibility(View.VISIBLE);

            onVirtualKeyboardViewShow();
        }

        protected abstract int getVirtualKeyboardSuggestedHeight();

        protected int getVirtualKeyboardExpectedHeight() {
            return mVirtualKeyboardViewHeight;
        }

        protected abstract void onVirtualKeyboardViewShow();

        void hideVirtualKeyboardView(boolean restoreAnchorLayoutParams) {
            mVirtualKeyboardView.getLayoutParams().height = 0;
            if (restoreAnchorLayoutParams) {
                onVirtualKeyboardViewHide();
                mAnchorView.requestLayout();
            }
        }

        /**
         * DON'T call {@link View#setLayoutParams(LayoutParams)} or apply a LayoutParams immediately!!!
         * {@link VirtualKeyboardController.LayoutManager} will call {@link View#requestLayout()} for you.
         * Otherwise, layout is called twice on the content view during a soft keyboard showing.
         */
        protected abstract void onVirtualKeyboardViewHide();

        boolean isVirtualKeyboardViewShown() {
            return mVirtualKeyboardView.isShown() && mVirtualKeyboardView.getHeight() > 0;
        }
    }
}
